//
// Created by Suzhen on 2016/12/17.
//

#include "AsyncEventGeneratorGroup.h"
#include "AsyncEventGenerator.h"

USING_ORION_V2;

AsyncEventGeneratorGroup::~AsyncEventGeneratorGroup() {
}

AsyncEventGeneratorGroup::AsyncEventGeneratorGroup(size_t clusterInitNum)
        : AsyncEventGeneratorGroup(
        [=](std::size_t n) {
//            if (n >= clusterInitNum) {
//                return (AsyncEventGenerator *) nullptr;//funny , if without cast , clang-parser will report an error , wtf???
//            }
            return n < clusterInitNum ? new AsyncEventGenerator : nullptr;
        }) {}

AsyncEventGeneratorGroup::AsyncEventGeneratorGroup(
        std::function<ORION_V2::AsyncEventGenerator *(std::size_t)> serverGen) {
    for (;;) {
        AsyncEventGenerator *s = serverGen(serverVec_.size());
        if (!s) {
            break;
        }
        serverVec_.push_back(s);
    }
}

ORION_V2::AsyncEventGenerator *AsyncEventGeneratorGroup::getLoadBalanceGenerator() {
    if (lbFlag_ > serverVec_.size()) {
        lbFlag_ = 0;
    }
    return getAsyncEventGeneratorAt(lbFlag_);
}

ORION_V2::AsyncEventGenerator *AsyncEventGeneratorGroup::getAsyncEventGeneratorWithCustomRule(
        std::function<std::size_t()> f) {
    return serverVec_.at(f());
}

ORION_V2::AsyncEventGenerator *AsyncEventGeneratorGroup::getAsyncEventGeneratorAt(std::size_t idx) {
    return serverVec_.at(idx);
}

Future<bool> AsyncEventGeneratorGroup::run() {
    std::lock_guard<std::mutex> guard(internalLock_);
    SYS_FAULT(status_ == INIT) << "AsyncEventGeneratorGroup run 状态错误 ,当前状态为 -> " << status_
                               << " , 请勿重复调用run函数";
    status_ = PREPARE_RUN;
    std::vector<Future<bool>> serverStatVec;
    for (std::size_t i = 0; i < serverVec_.size(); ++i) {
        AsyncEventGenerator *s = serverVec_.at(i);
        serverStatVec.push_back(s->startAsync());
    }
    collectAll<bool>(serverStatVec);
    status_ = RUNNING;
    runPromise_.setValue(true);
    return runPromise_.getFuture();
}

Future<bool> AsyncEventGeneratorGroup::stop() {
    std::lock_guard<std::mutex> guard(internalLock_);
    if (status_ == STOPPING || status_ == STOPPED) {
        return stopFuture();
    }
    CHECK(status_ == RUNNING) << "AsyncEventGeneratorGroup stop 状态错误 not RUNNING,当前状态为 -> " << status_;
    status_ = STOPPING;
    std::vector<Future<bool>> serverStatVec;
    for (std::size_t i = 0; i < serverVec_.size(); ++i) {
        AsyncEventGenerator *s = serverVec_.at(i);
        serverStatVec.push_back(s->stopAsync());
    }
    collectAll<bool>(serverStatVec);
    closePromise_.setValue(YES);
    return stopFuture();
}

AsyncEventGeneratorGroup::AsyncEventGeneratorGroupStatus
AsyncEventGeneratorGroup::getCurrentGroupStatus() const {
    return status_;
}

Future<bool> AsyncEventGeneratorGroup::stopFuture() {
    return closePromise_.getFuture();
}
